package com.course.file.service.impl;

import cn.hutool.core.io.FileUtil;
import com.course.file.config.FileUploadConfig;
import com.course.file.service.UploadService;
import com.course.server.dto.FileDto;
import com.course.server.enums.FileUseEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.Objects;

/**
 * @author: Durian
 * @date: 2021/5/22 15:52
 */
@Slf4j
@Service("location")
@ConditionalOnProperty(prefix = "upload", name = "address", havingValue = "location")
public class LocalUploadService implements UploadService {

    @Resource
    private FileUploadConfig fileUploadConfig;

    @Override
    public String upload(MultipartFile shard, FileDto fileDto) throws IOException {
        String key = fileDto.getKey();
        String suffix = fileDto.getSuffix();
        String name = fileDto.getName();
        String use = fileDto.getUse();
        Integer shardIndex = fileDto.getShardIndex();
        // 保存
        FileUseEnum fileUseEnum = FileUseEnum.get(use);
        // 文件夹不存在则创建
        String dir = fileUseEnum.name().toLowerCase();
        File directory = new File(fileUploadConfig.getLocation() + dir);
        if (!directory.exists()) {
            log.info("文件夹【{}】不存在，开始创建", fileUploadConfig.getLocation() + dir);
            boolean flag = directory.mkdirs();
            log.info("文件夹【{}】创建结果:{}", fileUploadConfig.getLocation() + dir, flag);
        }
        /*=========构建本地保存全路径=========*/
        // 拼接分片文件名
        String localPath = dir + File.separator + key + "." + suffix + "." + shardIndex;
        String path = dir + File.separator + key + "." + suffix;
        String fullPath = fileUploadConfig.getLocation() + localPath;
        shard.transferTo(new File(fullPath));
        log.info("文件【{}】保存到【{}】", name, fullPath);

        // 访问路径
        String imgPath = fileUploadConfig.getDomain() + path;
        fileDto.setPath(imgPath);
        // 合并分片文件
        if (Objects.equals(fileDto.getShardIndex(), fileDto.getShardTotal())) {
            merge(fileDto);
        }
        return imgPath;
    }

    @Override
    public String check(FileDto fileDto) {
        String dir = FileUseEnum.get(fileDto.getUse()).name().toLowerCase();
        String key = fileDto.getKey();
        String suffix = fileDto.getSuffix();
        String path = dir + "/" + key + "." + suffix;
        File file = new File(fileUploadConfig.getLocation() + path);
        return file.exists() ? fileUploadConfig.getDomain() + path : null;
    }

    /**
     * 合并分片文件
     *
     * @param fileDto 文件dto
     */
    private void merge(FileDto fileDto) {
        log.info("文件【{}】分片合并", fileDto.getName());
        String path = fileDto.getPath().replace(fileUploadConfig.getDomain(), "");
        int total = fileDto.getShardTotal();
        // 循环读取分片
        File newFile = new File(fileUploadConfig.getLocation() + path);
        for (int i = 0; i < total; i++) {
            byte[] bytes = FileUtil.readBytes(new File(fileUploadConfig.getLocation() + path + "." + (i + 1)));
            // 拼接分片
            FileUtil.writeBytes(bytes, newFile, 0, bytes.length, true);
        }
        log.info("分片文件合并完成【{}】", fileDto.getName());
        log.info("开始删除分片文件");
        for (int i = 0; i < total; i++) {
            FileUtil.del(new File(fileUploadConfig.getLocation() + path + "." + (i + 1)));
            log.info("分片文件【{}】删除完成", fileUploadConfig.getLocation() + path + "." + (i + 1));
        }
    }
}
